package com.yst.suivi.services.project.versions;

import java.io.IOException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;

import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.FinderException;
import javax.ejb.RemoveException;
import javax.ejb.SessionBean;
import javax.naming.NamingException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import com.yst.suivi.comparator.NameObjectComparator;
import com.yst.suivi.data.activities.Activity;
import com.yst.suivi.data.pointage.Pointage;
import com.yst.suivi.data.project.Project;
import com.yst.suivi.data.project.ProjectUtil;
import com.yst.suivi.data.project.versions.ProjectVersion;
import com.yst.suivi.data.project.versions.ProjectVersionLocalHome;
import com.yst.suivi.data.project.versions.ProjectVersionUtil;
import com.yst.suivi.data.user.User;
import com.yst.suivi.services.AbstractSessionBean;
import com.yst.suivi.services.activities.ActivityViewUtil;
import com.yst.suivi.services.pointage.PointageViewUtil;
import com.yst.suivi.status.StatusConstants;
import com.yst.suivi.status.StatusUtil;

/**
 * @ejb.bean display-name="ProjectVersionService"
 *           jndi-name="ProjectVersionHomeRemote" name="ProjectVersionView"
 *           type="Stateless" view-type="both"
 */
public class ProjectVersionServiceBean extends AbstractSessionBean implements SessionBean
{
	/**
	 * @throws CreateException
	 * @ejb.create-method view-type = "both"
	 */
	public void ejbCreate() throws CreateException
	{
		// by default nothing to do
	}

	/**
	 * This method create a new ProjectVersion.
	 * 
	 * @param standard
	 * @return standard updated
	 * @throws CreateException
	 * @ejb.interface-method view-type = "both"
	 * @ejb.transaction type = "Required"
	 */
	public String createProjectVersion(String nom, Project prj) throws NamingException, CreateException
	{
		checkConstraints(nom, "".intern(), prj);
		ProjectVersionLocalHome home = ProjectVersionUtil.getLocalHome();
		ProjectVersion projectVersion = home.create();
		updateObject(nom, prj, projectVersion);
		return projectVersion.getId();
	}

	/**
	 * The method checks if all the business constraints are verified.
	 * 
	 * @param login
	 * @param nom
	 * @param prenom
	 */
	private void checkConstraints(String version, String id, Project prj)
	{
		String[] parameter =
		{ "projectVersion", "version" };
		checkEmptyField(version, parameter);
		checkFieldLength(version, VERSION_FIELD_MAX_LENGTH, "version");
		StringBuffer buf = new StringBuffer();
		buf.append(" AND prjId='").append(prj.getId()).append("'");
		checkUnicity(version, "projectVersion", "version", id, buf.toString());
	}

	/**
	 * This method update a ProjectVersion.
	 * 
	 * @return standard updated
	 * @throws NamingException
	 * @throws FinderException
	 * @ejb.interface-method view-type = "both"
	 * @ejb.transaction type = "Required"
	 */
	public void storeProjectVersion(String id, String version) throws FinderException, NamingException
	{

		ProjectVersionLocalHome home = ProjectVersionUtil.getLocalHome();
		ProjectVersion projectVersion = home.findByPrimaryKey(id);
		checkConstraints(version, id, projectVersion.getProject());
		updateObject(version, projectVersion.getProject(), projectVersion);
	}

	/**
	 * The method closes the version of project. If a version of a project is
	 * close, all its activites are frozen.
	 * 
	 * @ejb.interface-method view-type = "both"
	 * @param id
	 * @throws FinderException
	 * @throws NamingException
	 * @throws CreateException
	 * @throws SQLException
	 */
	public void closeProjectVersion(String id) throws FinderException, NamingException, CreateException, SQLException
	{
		ProjectVersion prj = ProjectVersionUtil.getLocalHome().findByPrimaryKey(id);
		ActivityViewUtil.getLocalHome().create().closeProjectVersionActivity(prj);
		prj.setStatus(StatusConstants.CLOSE);
	}
	/**
	 * The method opens the version of project. 
	 * 
	 * @ejb.interface-method view-type = "both"
	 * @param id
	 * @throws FinderException
	 * @throws NamingException
	 * @throws CreateException
	 * @throws SQLException
	 */
	public void openProjectVersion(String id) throws FinderException, NamingException, CreateException, SQLException
	{
		ProjectVersion prj = ProjectVersionUtil.getLocalHome().findByPrimaryKey(id);
		prj.setStatus(StatusConstants.OPEN);
	}

	/**
	 * La methode remplie l'objet EJB avec les valeurs fournies
	 * 
	 * @param version
	 * @param prj
	 * @param projectVersion
	 */
	private void updateObject(String version, Project prj, ProjectVersion projectVersion)
	{
		projectVersion.setVersion(version);
		projectVersion.setProject(prj);
	}

	/**
	 * This method delete a ProjectVersion.
	 * 
	 * @param standard
	 * @throws NamingException
	 * @throws RemoveException
	 * @throws EJBException
	 * @throws FinderException
	 * @ejb.interface-method view-type = "both"
	 * @ejb.transaction type = "Required"
	 */
	public void deleteProjectVersion(String id) throws NamingException, EJBException, RemoveException
	{
		ProjectVersionLocalHome home = ProjectVersionUtil.getLocalHome();
		home.remove(id);
	}

	/**
	 * The method returns all the projectVersion of the given project primary
	 * key
	 * 
	 * @param prjId
	 * @return
	 * @throws FinderException
	 * @throws NamingException
	 * @ejb.interface-method view-type = "both"
	 */

	public Collection findProjectVersion(String prjId) throws FinderException, NamingException
	{
		Project prj = ProjectUtil.getLocalHome().findByPrimaryKey(prjId);
		ArrayList retour = new ArrayList(ProjectVersionUtil.getLocalHome().findByProject(prj));
		Collections.sort(retour, NameObjectComparator.comparator);
		return retour;
	}

	/**
	 * The method returns the projectVersion identify by the primary key
	 * 
	 * @param projectVersionKey
	 * @return
	 * @throws FinderException
	 * @throws NamingException.
	 * @ejb.interface-method view-type = "both"
	 */
	public ProjectVersion findProjectVersionByKey(String projectVersionKey) throws FinderException, NamingException
	{
		return ProjectVersionUtil.getLocalHome().findByPrimaryKey(projectVersionKey);
	}

	/**
	 * @ejb.interface-method view-type = "both"
	 * @param prjId
	 * @return
	 * @throws NamingException
	 * @throws SQLException
	 * @throws IOException
	 * @throws CreateException
	 * @throws FinderException
	 */
	public HSSFWorkbook report(ProjectVersion prjVersion) throws NamingException, SQLException, IOException, FinderException, CreateException
	{
		final short NOM_COLUMN = 0;
		final short USER_COLUMN = 2;
		final short STATUS_COLUMN = 3;
		final short DUREE_COLUMN = 4;
		final short CONS_COLUMN = 5;
		final short RAF_COLUMN = 6;
		int rowIndex = 2;
		HSSFRow row;
		HSSFWorkbook book = null;

		book = new HSSFWorkbook(ProjectVersionServiceBean.class.getResourceAsStream("/templates/rapports/rapport_activite1.xls"));
		HSSFSheet sheet = book.getSheetAt(0);
		row = getRow(rowIndex, sheet);
		getCell((short) 1, row).setCellValue(prjVersion.getProject().getNom());
		getCell((short) 3, row).setCellValue(prjVersion.getVersion());
		rowIndex++;
		row = getRow(rowIndex, sheet);
		DateFormat dteFormat = new SimpleDateFormat("dd/MM/yyyy");
		getCell((short) 1, row).setCellValue(dteFormat.format(Calendar.getInstance().getTime()));
		rowIndex = 7;
		Iterator rs = ActivityViewUtil.getLocalHome().create().findByProject(prjVersion.getId()).iterator();
		StringBuffer buf;
		Activity act;
		Iterator itUsr;
		User usr;
		boolean isFirstUser;
		// pass all the results
		while (rs.hasNext())
		{
			act = (Activity) rs.next();
			row = getRow(rowIndex, sheet);
			getCell(NOM_COLUMN, row).setCellValue(act.getNom());
			getCell(DUREE_COLUMN, row).setCellValue(act.getDuree().floatValue());
			getCell(RAF_COLUMN, row).setCellValue(act.getRaf().floatValue());
			getCell(CONS_COLUMN, row).setCellValue(getActWorkload(act));
			getCell(STATUS_COLUMN, row).setCellValue(StatusUtil.getStatusName(act.getStatus()));
			buf = new StringBuffer();
			isFirstUser = true;
			itUsr = ActivityViewUtil.getLocalHome().create().getAffectedUser(act).iterator();
			while (itUsr.hasNext())
			{
				usr = (User) itUsr.next();
				if (!isFirstUser)
				{
					buf.append(", ");
				}
				else
				{
					isFirstUser = false;
				}
				buf.append(usr.getFullname());
			}
			getCell(USER_COLUMN, row).setCellValue(buf.toString());
			rowIndex++;
		}

		return book;
	}

	/**
	 * @param usr
	 * @param retour
	 * @param cal
	 * @param act
	 * @return
	 * @throws NamingException
	 * @throws FinderException
	 * @throws CreateException
	 */
	private float getActWorkload(Activity act) throws NamingException, FinderException, CreateException
	{
		float retour = 0f;

		Pointage pointage;
		Collection col = PointageViewUtil.getLocalHome().create().findByAct(act);
		Iterator it = col.iterator();
		while (it.hasNext())
		{
			pointage = (Pointage) it.next();
			switch (pointage.getTempsPos().intValue())
			{
			case 1:
				retour = retour + 0.25f;
				break;
			case 2:
				retour = retour + 0.5f;
				break;
			case 3:
				retour = retour + 0.75f;
				break;
			case 4:
				retour = retour + 1.0f;
				break;
			default:
				break;
			}
		}
		return retour;
	}

	/**
	 * The method returns the cell corresponding to the column of the row. If it
	 * doesn't exist, a new one is created
	 * 
	 * @param column
	 * @param row
	 * @return
	 */
	public static HSSFCell getCell(short column, HSSFRow row)
	{
		HSSFCell cell;
		cell = row.getCell(column);
		if (null == cell)
		{
			cell = row.createCell(column);
		}
		return cell;
	}

	/**
	 * The method returns the row indeicate bye the rowNumber. If the row
	 * doesn't exist, a new one is created.
	 * 
	 * @param rowNumber
	 * @param sheet
	 * @return
	 */
	public static HSSFRow getRow(int rowNumber, HSSFSheet sheet)
	{
		HSSFRow row;
		row = sheet.getRow(rowNumber);
		if (null == row)
		{
			row = sheet.createRow(rowNumber);
		}
		return row;
	}
}
